﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.IO;
using System.Reflection;
using log4net;

namespace PreCommitHook
{
    /// <summary>
    /// gets the executing assembly by the file which is committed and create a xml file with reference, so the hook will check first against it
    /// rather than looping through all proj files
    /// </summary>
    public class AssemblyHelper
    {
        static ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        internal static bool AssemblyNameMatch(string changedItemPath, string assemblyName)
        {
            string[] parts = changedItemPath.Split('/');
            foreach(string part in parts)
            {
                if (part == assemblyName) return true;
            }
            return false;
        }
        /// <summary>
        /// get the assembly name from the project file and if doesnt exists in SolutionAssemblies.xml append it to its content
        /// </summary>
        /// <param name="csProjFileContent"></param>
        public static string GetExecutingAssembly(string csProjFileName, string csProjFileContent, string committedFileName)
        {
            XDocument xDoc = XDocument.Parse(csProjFileContent);
            LinqToXmlHelper.StripNamespaces(xDoc.Root);

            var itemGroups = (from el in xDoc.Root.Elements("ItemGroup").Elements()
                              where el.Name.LocalName.Equals("Compile") && ((string)el.Attribute("Include")).Contains(committedFileName)
                                      select el);
    
            if (itemGroups.ToList().Count > 0)
            {
                //get the assembly and append to xml content
                var assemblyNameQuery = (from el in xDoc.Root.Element("PropertyGroup").Elements()
                                         where el.Name.LocalName.Equals("AssemblyName")
                                         select el.Value);

                IList<string> assembly = assemblyNameQuery.ToList<string>();
                if (assembly.Count != 1)
                {
                    log.Fatal(String.Format("No assembly name or more than one was found in the project files for file '{0}'", committedFileName));
                    throw new ArgumentException(String.Format("No assembly name or more than one was found in the project files for file '{0}'", committedFileName));
                }
                string assemblyName = assembly[0] + ".dll";

                return assemblyName;

            }

            return string.Empty; //if no match found
        }
        /// <summary>
        ///gets the assembly from SolutionAssemblies\SolutionAssemblies.xml if exists
        ///if more than one file with the same name belongs to a certain assembly
        /// </summary>
        /// <returns>assembly name</returns>
        internal static bool GetAssemblyNameFromFileIfExists(string fileName, string projectNameFile, ref string assemblyName)
        {
            string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            XDocument xDoc = XDocument.Load(path + @"\SolutionAssemblies\SolutionAssemblies.xml");
            var assmeblyExists = (from el in xDoc.Root.Elements().Elements("contentFiles")
                                  from files in el.Elements("file")
                                  where files.Value == fileName && files.Parent == el && el.Parent.Attribute("projFileName").Value == projectNameFile
                                  select new
                                  {
                                      AssemblyName = el.Parent.Attribute("name").Value,
                                      FileName = files.Value
                                  }
                                  );

            if (assmeblyExists.ToList().Count != 1) return false;

            assemblyName = assmeblyExists.ToList()[0].AssemblyName;
            return true;

        }

        /// <summary>
        /// /trunk/RolesRepository.cs returns RolesRepository.cs
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static string GetFileNameFromPath(string input)
        {
           return input.Substring(input.LastIndexOf("/") + 1);
        }

        public static bool IsCodeFile(string file)
        {
            return file.Substring(file.LastIndexOf(".") + 1) == "cs";
        }

        public static string GetCSFileWithoutExtension(string file)
        {
            return file.Substring(0, file.LastIndexOf('.'));

        }
    }
}
